﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Web.Mvc;
using System.Xml.Linq;
using Xenta.Attributes;
using Xenta.Utils;
using Xenta.Web.Controllers;

namespace Xenta.Web.Areas.Forum.Controllers
{
    public sealed class ForumController : ExtController
    {
        #region GET/POST Actions

        [HttpGet]
        public ActionResult Index()
        {
            var m = Svc.ProcessOperation("SearchForums", new
            {
                ParentID = 0,
                SortBy = new[] 
                {
                    "DisplayOrder"
                }
            }, new
            {
                DisclosureLevel = "Base",
                DisclosureOptions = new Dictionary<String, String>
                {
                    { "TranslatedTo", JDM.String(Svc.Localization.Language.Code) }
                }.Unload()
            });
            return View(m);
        }

        [HttpGet]
        public ActionResult Search(string searchTerm, int? memberID, int? page)
        {
            dynamic m = new ExpandoObject();

            page = page.HasValue ? page.Value : 0;
            m.CountPerPage = Svc.Config(Par.In("WebPortal").Of(this).Group("Search").Name("Count"), 10);
            m.Topics = Svc.ProcessOperation("SearchForumTopics", new
            {
                Term = new
                {
                    Expression = String.Format("%{0}%", searchTerm)
                },
                MemberID = memberID,
                Index = page * m.CountPerPage,
                Count = m.CountPerPage,
                SortBy = new[] 
                {
                    "CreatedOn"
                },
                SortDir = "Descending"
            }, new
            {
                DisclosureLevel = "Base"
            });
            return View(m);
        }

        [HttpGet]
        public ActionResult Show(int id, string searchTerm, int? page)
        {
            page = page.HasValue ? page.Value : 0;
            dynamic m = new ExpandoObject();

            m.Forum = Svc.ProcessOperation("GetForum", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Entire",
                DisclosureOptions = new Dictionary<String, String>
                {
                    { "TranslatedTo", JDM.String(Svc.Localization.Language.Code) }
                }.Unload()
            });
            if(m.Forum == null)
                return HttpNotFound();

            m.UserCanWrite = Svc.IsAuthenticated;
            m.UserCanModerate = false;
            var acl = m.Forum.AccessRules
                as IEnumerable<dynamic>;
            if(acl.Any())
            {
                var tmp = acl.Where(x => Svc.InRole((string)JDM.String(x.Role.Code)))
                    .Select(x => JDM.String(x.AccessRights));
                m.UserCanModerate = tmp.Any(x => x.Contains("Moderate"));
                m.UserCanWrite = m.UserCanModerate || tmp.Any(x => x.Contains("ReadWrite"));
            }

            m.Forums = Svc.ProcessOperation("SearchForums", new
            {
                ParentID = JDM.Int32(m.Forum.EntityID),
                SortBy = new[] 
                {
                    "DisplayOrder"
                }
            }, new
            {
                DisclosureLevel = "Base",
                DisclosureOptions = new Dictionary<String, String>
                {
                    { "TranslatedTo", JDM.String(Svc.Localization.Language.Code) }
                }.Unload()
            });
            
            m.CountPerPage = Svc.Config(Par.In("WebPortal").Of(this).Group("Show").Name("Count"), 10);
            m.Topics = Svc.ProcessOperation("SearchForumTopics", new
            {
                Term = new
                {
                    Expression = String.Format("%{0}%", searchTerm)
                },
                ForumID = JDM.Int32(m.Forum.EntityID),
                Index = page * m.CountPerPage,
                Count = m.CountPerPage,
                FlagMask = "General,Question",
                SortBy = new[] 
                {
                    "CreatedOn"
                },
                SortDir = "Descending"
            }, new
            {
                DisclosureLevel = "Base"
            });
            return View(m);
        }

        #endregion

        #region Child Actions

        [ChildActionOnly]
        public ActionResult _Announcments(int forumID)
        {
            var m = Svc.ProcessOperation("SearchForumTopics", new
            {
                ForumID = forumID,
                FlagMask = "Announcement",
                SortBy = new[] 
                {
                    "CreatedOn"
                },
                SortDir = "Descending"
            }, new
            {
                DisclosureLevel = "Base"
            });
            return PartialView(m);
        }

        [ChildActionOnly]
        public ActionResult _Breadcrumb(int id, bool full)
        {
            var m = new List<dynamic>();
            var f = Svc.ProcessOperation("GetForum", new
            {
                EntityID = id
            }, new
            {
                DisclosureLevel = "Base",
                DisclosureOptions = new Dictionary<String, String>
                {
                    { "TranslatedTo", JDM.String(Svc.Localization.Language.Code) }
                }.Unload()
            });
            if(f == null)
                return PartialView(m);

            if(full)
                m.Add(f);
            if(f.Parent != null)
            {
                int parentID = JDM.Int32(f.Parent.EntityID);
                while(parentID != 0)
                {
                    var p = Svc.ProcessOperation("GetForum", new
                    {
                        EntityID = id
                    }, new
                    {
                        DisclosureLevel = "Base",
                        DisclosureOptions = new Dictionary<String, String>
                        {
                            { "TranslatedTo", JDM.String(Svc.Localization.Language.Code) }
                        }.Unload()
                    });
                    if(p == null)
                        break;
                    m.Add(p);
                    parentID = p.Parent == null ? 0 : JDM.Int32(p.Parent.EntityID);
                }
                m.Reverse();
            }
            return PartialView(m);
        }

        [ChildActionOnly, ActionCache("short", true, VaryByCustom = "locale")]
        public ActionResult _MemberByPostCount()
        {
            string rptMimeType = String.Empty;
            long rptElapsedTime = 0;
            int num = Svc.Config(Par.In("WebPortal").Of(this)
                .Group("_MemberByPostCount")
                .Name("Num"), 25);
            dynamic m = new ExpandoObject();

            m.Error = String.Empty;
            m.Data = null;
            try
            {
                using(var rptData = Svc.BuildReport("TopNForumMemberByPostCountReport",
                    new Dictionary<String, String>
                    {
                        {"num", num.ToString()}
                    },
                    out rptMimeType,
                    out rptElapsedTime))
                {
                    m.Data = XElement.Load(rptData);
                }
            }
            catch(Exception ex)
            {
                m.Error = ex.ToString();
            }
            m.ElapsedTime = rptElapsedTime;

            return PartialView(m);
        }

        [ChildActionOnly, ActionCache("short", true, VaryByCustom = "locale")]
        public ActionResult _MemberByKarmaPoints()
        {
            string rptMimeType = String.Empty;
            long rptElapsedTime = 0;
            int num = Svc.Config(Par.In("WebPortal").Of(this)
                .Group("_MemberByKarmaPoints")
                .Name("Num"), 25);
            dynamic m = new ExpandoObject();

            m.Error = String.Empty;
            m.Data = null;
            try
            {
                using(var rptData = Svc.BuildReport("TopNForumMemberByKarmaPointsReport",
                    new Dictionary<String, String>
                    {
                        {"num", num.ToString()}
                    },
                    out rptMimeType,
                    out rptElapsedTime))
                {
                    m.Data = XElement.Load(rptData);
                }
            }
            catch(Exception ex)
            {
                m.Error = ex.ToString();
            }
            m.ElapsedTime = rptElapsedTime;

            return PartialView(m);
        }

        [ChildActionOnly, ActionCache("short", true, VaryByCustom = "locale")]
        public ActionResult _MembersOnline()
        {
            string rptMimeType = String.Empty;
            long rptElapsedTime = 0;
            int num = Svc.Config(Par.In("WebPortal").Of(this)
                .Group("_MembersOnline")
                .Name("Num"), 1000);
            dynamic m = new ExpandoObject();
            m.Error = String.Empty;
            m.Data = null;

            try
            {
                using(var rptData = Svc.BuildReport("ForumMembersOnlineReport",
                    new Dictionary<String, String>
                    {
                        {"num", num.ToString()}
                    },
                    out rptMimeType,
                    out rptElapsedTime))
                {
                    m.Data = XElement.Load(rptData);
                }
            }
            catch(Exception ex)
            {
                m.Error = ex.ToString();
            }
            m.ElapsedTime = rptElapsedTime;

            return PartialView(m);
        }

        #endregion
    }
}
